home *** CD-ROM | disk | FTP | other *** search
/ Aminet 15 / Aminet 15 - Nov 1996.iso / Aminet / comm / bbs / s342q16.lha / floors.c < prev    next >
C/C++ Source or Header  |  1996-08-31  |  20KB  |  951 lines

  1. /*
  2. *       Floors.c
  3. *
  4. * Floor handling code for Citadel-86.
  5. */
  6. #include "ctdl.h"
  7. /*
  8. *       Contents
  9. */
  10. char SelDirs = FALSE,
  11. SelShared = FALSE,
  12. SelPriv = FALSE,
  13. SelRO = FALSE,
  14. SelNew = FALSE,
  15. SelAnon = FALSE;
  16. char ShowNew;
  17. char NotForgotten = TRUE;
  18. char JustChecking;
  19. char HasSkipped;
  20. static char maim;
  21. char FoundNew;
  22. static int  GlobalFloor;
  23. static int  MoveCount;
  24. extern struct floor  *FloorTab;
  25. extern rTable    *roomTab;
  26. extern CONFIG    cfg;
  27. extern aRoom     roomBuf;
  28. extern logBuffer logBuf;
  29. extern MessageBuffer   msgBuf;
  30. extern char      remoteSysop;
  31. extern int       thisRoom;
  32. extern char      loggedIn;       /* Are we logged in?            */
  33. extern int       TopFloor;
  34. extern char      *confirm;
  35. extern char      outFlag;
  36. extern char      onConsole;
  37. extern char      *baseRoom;
  38. static int FlagCheck(int i);
  39. int FindFloor(label name, char doPartial);
  40. /*
  41. * FloorRunner()
  42. *
  43. * This function runs through all the rooms on a floor, applying the given
  44. * function to all rooms on that floor.
  45. */
  46. int FloorRunner(int start, int (*func)(int r))
  47.   {
  48.   int rover, CurrentFloor;
  49.   if (start == ERROR) return ERROR;
  50.   CurrentFloor = roomTab[start].rtFlIndex;
  51.   if (!FloorTab[CurrentFloor].FlInuse)
  52.   CurrentFloor = 0;
  53.   /* start with current room, go through table */
  54.   for (rover = 0; rover < MAXROOMS; rover++)
  55.     {
  56.     /* deep breath ... should rewrite this, prime example of
  57.     programming via accretion. */
  58.     if (!FloorTab[roomTab[rover].rtFlIndex].FlInuse)
  59.     roomTab[rover].rtFlIndex = 0;
  60.     if ( roomTab[rover].rtFlIndex == CurrentFloor && (KnownRoom(rover) ||
  61.     (NotForgotten && roomTab[rover].rtflags.INUSE &&
  62.     (aide && (cfg.BoolFlags.aideSeeAll || onConsole) &&
  63.     (!roomTab[rover].rtflags.INVITE || SomeSysop())))))
  64.       {
  65.       if ((*func)(rover)) return rover;
  66.  
  67.       }
  68.  
  69.     }
  70.   return ERROR;
  71.  
  72.   }
  73. /*
  74. * NewRoom()
  75. *
  76. * This function gets next new room in system (like GotoRoom()) on the current
  77. * floor.
  78. */
  79. int NewRoom()
  80.   {
  81.   int CurrentFloor, OldFloor, roomNo;
  82.   OldFloor = thisFloor;
  83.   CurrentFloor = -1;
  84.   while (   (roomNo = FloorRunner(thisRoom, NSRoomHasNew)) == ERROR &&
  85.   CurrentFloor != TopFloor     )
  86.     {
  87.     thisRoom = FirstRoom(++CurrentFloor);
  88.  
  89.     }
  90.   if (CurrentFloor == TopFloor)
  91.   roomNo = 0;           /* no new-message rooms found */
  92.   getRoom(roomNo);
  93.   mPrintf("%s\n ", roomBuf.rbname);
  94.   /* really ugly kludge.  someday locate this gunk in gotoRoom() */
  95.   if (!KnownRoom(thisRoom))
  96.     {
  97.     SetKnown(0, MAXVISIT - 1, thisRoom, &logBuf);
  98.  
  99.     }
  100.   return !(OldFloor == roomTab[thisRoom].rtFlIndex);
  101.  
  102.   }
  103. /*
  104. * FirstRoom()
  105. *
  106. * This function gets the first room on the specified floor.
  107. */
  108. int FirstRoom(int FloorNo)
  109.   {
  110.   int rover;
  111.   for (rover = 0; rover < MAXROOMS; rover++)
  112.     {
  113.     if (     roomTab[rover].rtflags.INUSE &&
  114.     roomTab[rover].rtFlIndex == FloorNo    )
  115.     return rover;
  116.  
  117.     }
  118.   return ERROR;
  119.  
  120.   }
  121. /*
  122. * DoFloor()
  123. *
  124. * This function handles the fanout for floor commands.
  125. */
  126. int DoFloors()
  127.   {
  128.   int  toReturn;
  129.   char again, c[2];
  130.   char *FloorOpts[] =
  131.     {
  132.     TERM "Aide", TERM "Z\bForget", TERM "Skip",
  133.     TERM "Goto", TERM "Known Floors", TERM "C\b", ""
  134.  
  135.     };
  136.   SListBase  FSelects =
  137.     {
  138.     NULL, FindSelect, NULL, NoFree, NULL
  139.  
  140.     };
  141.   do
  142.     {
  143.     toReturn = GOOD_SELECT;
  144.     if (CmdMenuList(FloorOpts, &FSelects, "floor.mnu", c, TRUE, FALSE)
  145.     == BACKED_OUT) return GOOD_SELECT;
  146.     again = FALSE;
  147.     switch (c[0])
  148.       {
  149.       case 'A': toReturn = FAide();     break;
  150.       case 'Z': toReturn = FForget();     break;
  151.       case 'S':
  152.       case 'G': toReturn = FGotoSkip(c[0]);   break;
  153.       case 'K': toReturn = FKnown(ONLY_FLOORS);   break;
  154.       case 'C': toReturn = FConfigure();      break;
  155.       default:
  156.       ;
  157.  
  158.       }
  159.     if (toReturn == BACKED_OUT)
  160.       {
  161.       again = TRUE;
  162.       PushBack('\b');
  163.  
  164.       }
  165.  
  166.     }
  167.   while (again);
  168.   return toReturn;
  169.  
  170.   }
  171. /*
  172. * FInvite()
  173. *
  174. * This function is used to invite a user to all rooms on a floor.
  175. */
  176. void FInvite()
  177.   {
  178.   mPrintf("[%s]\n ", FloorTab[thisFloor].FlName);
  179.   getList(UserToFloor, "Invited users", NAMESIZE, FALSE);
  180.  
  181.   }
  182. static char YesInvite = TRUE;
  183. /*
  184. * FWithdraw()
  185. *
  186. * This function will withdraw invitations from a floor.
  187. */
  188. void FWithdraw()
  189.   {
  190.   mPrintf("[%s]\n ", FloorTab[thisFloor].FlName);
  191.   YesInvite = FALSE;
  192.   getList(UserToFloor, "Kicked out users", NAMESIZE, FALSE);
  193.   YesInvite = TRUE;
  194.  
  195.   }
  196. extern logBuffer logTmp;
  197. /*
  198. * UserToFloor()
  199. *
  200. * This function will invite the named user to current floor.  This function
  201. * is used in conjunction with getList().
  202. */
  203. int UserToFloor(char *name)
  204.   {
  205.   int logNo;
  206.   int InviteUserToFloor(int r);
  207.   logNo = findPerson(name, &logTmp);
  208.   if (logNo == ERROR)
  209.     Output_Citadel_Message("NODRFD", (long)name,NULL,NULL);
  210.   else
  211.     {
  212.     FloorRunner(thisRoom, InviteUserToFloor);
  213.     putLog(&logTmp, logNo);
  214.  
  215.     }
  216.   return TRUE;
  217.  
  218.   }
  219. /*
  220. * InviteUserToFloor()
  221. *
  222. * This function does the actual work of inviting a user.
  223. */
  224. int InviteUserToFloor(int r)
  225.   {
  226.   if (r != AIDEROOM)
  227.     {
  228.     if (YesInvite)
  229.     logTmp.lbgen[r] = (roomTab[r].rtgen << GENSHIFT) + MAXVISIT - 1;
  230.     else
  231.     logTmp.lbgen[r] = ((roomTab[r].rtgen + (MAXGEN-1)) % MAXGEN);
  232.  
  233.     }
  234.   return FALSE;
  235.  
  236.   }
  237. /*
  238. * FSkipped()
  239. *
  240. * This function will show skipped rooms and floors.
  241. */
  242. void FSkipped()
  243.   {
  244.   int rover, roomNo;
  245.   JustChecking = FALSE;
  246.   ShowNew = TRUE;
  247.   Output_Citadel_Message("SKPRMF",(long) FloorTab[thisFloor].FlName , NULL, NULL);
  248.   FloorRunner(thisRoom, SkippedNewRoom);
  249.   ShowNew = FALSE;
  250.   JustChecking = TRUE;
  251.   Output_Citadel_Message("SKPFLR", NULL, NULL, NULL);
  252.   for (rover = 1; rover < TopFloor; rover++)
  253.     {
  254.     roomNo = FirstRoom(rover);
  255.     if (FloorRunner(roomNo, SkippedNewRoom) != ERROR)
  256.       Output_Citadel_Message("FLRNNL",(long)FloorTab[rover].FlName , NULL, NULL);
  257.  
  258.     }
  259.   JustChecking = FALSE;
  260.   tableRunner(SkippedNewRoom, TRUE);
  261.  
  262.   }
  263. /*
  264. * FForget()
  265. *
  266. * This function will forget a floor.
  267. */
  268. char FForget()
  269.   {
  270.   Output_Citadel_Message("FLOORN",(long)FloorTab[roomTab[thisRoom].rtFlIndex].FlName, NULL, NULL);
  271.   if (!getYesNo("CONFRM")) return GOOD_SELECT;
  272.   FloorRunner(thisRoom, Zroom);
  273.   gotoRoom(baseRoom, 'S');
  274.   return GOOD_SELECT;
  275.  
  276.   }
  277. /*
  278. * FConfigure()
  279. *
  280. * This function will change floor configuration value.
  281. */
  282. char FConfigure()
  283.   {
  284.   FloorMode = !FloorMode;
  285.   mPrintf("%s mode\n ", (FloorMode) ? "FLOOR" : "Normal");
  286.   return GOOD_SELECT;
  287.  
  288.   }
  289. /*
  290. * FGotoSkip()
  291. *
  292. * This function will let us Skip an entire floor.
  293. */
  294. char FGotoSkip(int mode)
  295.   {
  296.   label floorName;
  297.   int   floorNo, newRoom, rover;
  298.   char  dispbuf[40];
  299.   outFlag = IMPERVIOUS;
  300.   if (mode == 'S')
  301.     {
  302.     sPrintf(dispbuf, "[%s] goto ",
  303.     FloorTab[roomTab[thisRoom].rtFlIndex].FlName);
  304.     mPrintf("%s", dispbuf);
  305.  
  306.     }
  307.   if (getNormStr("", floorName, NAMESIZE, BS_VALID) == BACKED_OUT)
  308.     {
  309.     if (mode == 'S')
  310.     for (rover = 0; rover < strLen(dispbuf); rover++)
  311.     mPrintf("\b \b");
  312.     return BACKED_OUT;
  313.  
  314.     }
  315.   if (strLen(floorName) != 0)
  316.     {
  317.     if ((floorNo = FindFloor(floorName, TRUE)) == ERROR)
  318.       {
  319.       Output_Citadel_Message("NODRFD", (long)floorName,NULL, NULL);
  320.       return GOOD_SELECT;
  321.  
  322.       }
  323.     if ((newRoom = FloorRunner(FirstRoom(floorNo), FindAny)) == ERROR)
  324.       {
  325.       Output_Citadel_Message("NOKNRM",(long) FloorTab[floorNo].FlName, NULL, NULL );
  326.       return GOOD_SELECT;
  327.  
  328.       }
  329.  
  330.     }
  331.   else
  332.     {
  333.     floorNo = thisFloor;
  334.     for (rover = 0; rover < TopFloor; rover++)
  335.     if (rover != floorNo && FloorTab[rover].FlInuse)
  336.       {
  337.       newRoom = FirstRoom(rover);
  338.       if ((newRoom = FloorRunner(newRoom, NSRoomHasNew)) != ERROR)
  339.       break;
  340.  
  341.       }
  342.     if (rover == TopFloor)
  343.     newRoom = 0;
  344.  
  345.     }
  346.   if (mode == 'S') FloorRunner(thisRoom, FSroom);
  347.   gotoRoom(roomTab[newRoom].rtname, mode);
  348.   return GOOD_SELECT;
  349.  
  350.   }
  351. /*
  352. * FindFloor()
  353. *
  354. * This function returns index for the given floor name.
  355. */
  356. int FindFloor(label name, char doPartial)
  357.   {
  358.   int rover;
  359.   for (rover = 0; rover < TopFloor; rover++)
  360.     {
  361.     if (strCmpU(name, FloorTab[rover].FlName) == SAMESTRING &&
  362.     FloorTab[rover].FlInuse)
  363.       {
  364.       return rover;
  365.  
  366.       }
  367.  
  368.     }
  369.   if (doPartial)
  370.   for (rover = 0; rover < TopFloor; rover++)
  371.     {
  372.     if (FloorTab[rover].FlInuse &&
  373.     matchString(FloorTab[rover].FlName, name,
  374.     lbyte(FloorTab[rover].FlName)) != NULL)
  375.     return rover;
  376.  
  377.     }
  378.   return ERROR;
  379.  
  380.   }
  381. /*
  382. * FAide()
  383. *
  384. * This function handles the floor-oriented aide commands.
  385. */
  386. char FAide()
  387.   {
  388.   char *FloorAideOpts[] =
  389.     {
  390.     "Create Floor\n", "Delete empty floors\n", "Move rooms\n",
  391.     "Kill Floor\n", "Rename Floor\n", "Floor moderator\n",
  392.     "Invite users to floor", "Withdraw users from floor", "\b", ""
  393.  
  394.     };
  395.   if (!aide)
  396.     {
  397.     if (loggedIn && strCmpU(logBuf.lbname, FloorTab[thisFloor].FlModerator) ==
  398.     SAMESTRING)
  399.       {
  400.       RenameFloor();
  401.       return GOOD_SELECT;
  402.  
  403.       }
  404.     else
  405.     return BAD_SELECT;    /* Indicates problem */
  406.  
  407.     }
  408.   RegisterThisMenu("aideflr.mnu", FloorAideOpts);
  409.   switch (GetMenuChar())
  410.     {
  411.     case 'C': CreateFloor();      break;
  412.     case 'D': DeleteFloors();     break;
  413.     case 'M': MoveRooms();        break;
  414.     case 'K': KillFloor();        break;
  415.     case 'R': RenameFloor();      break;
  416.     case 'F': FlModerator();      break;
  417.     case 'I': FInvite();        break;
  418.     case 'W': FWithdraw();        break;
  419.     case '\b': return BACKED_OUT;
  420.  
  421.     }
  422.   return GOOD_SELECT;
  423.  
  424.   }
  425. /*
  426. * FlModerator()
  427. *
  428. * This function handles the floor moderator.
  429. */
  430. void FlModerator()
  431.   {
  432.   label buffer;
  433.   if (WhoIsModerator(buffer))
  434.     {
  435.     strCpy(FloorTab[thisFloor].FlModerator, buffer);
  436.     putFloor(thisFloor);
  437.     ZeroMsgBuffer(&msgBuf);
  438.     sPrintf(msgBuf.mbtext, "%s's moderator set to %s by %s.",
  439.     FloorTab[thisFloor].FlName, buffer, logBuf.lbname);
  440.     aideMessage(NULL,FALSE);
  441.  
  442.     }
  443.  
  444.   }
  445. /*
  446. * DeleteFloors()
  447. *
  448. * This function deletes empty floors.
  449. */
  450. void DeleteFloors()
  451.   {
  452.   int rover, count = 0;
  453.   ZeroMsgBuffer(&msgBuf);
  454.   sPrintf(msgBuf.mbtext, "Following empty floors deleted by %s: ",
  455.   logBuf.lbname);
  456.   for (rover = 1; rover < TopFloor; rover++)
  457.     {
  458.     if (FloorTab[rover].FlInuse)
  459.       {
  460.       if (FirstRoom(rover) == ERROR)
  461.         {
  462.         count++;
  463.         FloorTab[rover].FlInuse = FALSE;
  464.         putFloor(rover);
  465.         sPrintf(lbyte(msgBuf.mbtext), "[%s], ", FloorTab[rover].FlName);
  466.  
  467.         }
  468.  
  469.       }
  470.  
  471.     }
  472.   if (count)
  473.     {
  474.     *(lbyte(msgBuf.mbtext) - 2) = '.';
  475.     *(lbyte(msgBuf.mbtext) - 1) = 0;
  476.  
  477.     }
  478.   aideMessage(NULL,FALSE);
  479.  
  480.   }
  481. /*
  482. * MoveRooms()
  483. *
  484. * This function moves a series of rooms into the current floor.
  485. */
  486. void MoveRooms()
  487.   {
  488.   int   CurrentRoom;
  489.   char  *end;
  490.   CurrentRoom = thisRoom;
  491.   GlobalFloor = thisFloor;
  492.   MoveCount = 0;
  493.   ZeroMsgBuffer(&msgBuf);
  494.   sPrintf(msgBuf.mbtext, "Following rooms moved to floor %s by %s: ",
  495.   FloorTab[thisFloor].FlName, logBuf.lbname);
  496.   getList(MoveToFloor, "Rooms to move to this floor", NAMESIZE, FALSE);
  497.   getRoom(CurrentRoom);       /* MoveToFloor changes thisRoom & roomBuf */
  498.   if (MoveCount != 0)
  499.     {
  500.     end = lbyte(msgBuf.mbtext);
  501.     *(end - 2) = '.';
  502.     *(end - 1) = 0;
  503.     aideMessage(NULL,FALSE);
  504.  
  505.     }
  506.  
  507.   }
  508. /*
  509. * MoveToFloor()
  510. *
  511. * This function will move a single room to a floor.
  512. */
  513. int MoveToFloor(char *name)
  514.   {
  515.   int roomNo;
  516.   if ((roomNo = roomExists(name)) == ERROR)
  517.     {
  518.     Output_Citadel_Message("NOROOM",(long)name,NULL,NULL);
  519.     return TRUE;
  520.  
  521.     }
  522.   if (   roomNo == LOBBY  ||  roomNo == MAILROOM  ||  roomNo == AIDEROOM  )
  523.     {
  524.     if (!getYesNo("WRMVSP")) return TRUE;
  525.  
  526.     }
  527.   MoveCount++;
  528.   getRoom(roomNo);
  529.   roomBuf.rbFlIndex = GlobalFloor;
  530.   putRoom(roomNo);
  531.   noteRoom();
  532.   sPrintf(lbyte(msgBuf.mbtext), "%s, ", formRoom(thisRoom, FALSE, FALSE));
  533.   return TRUE;
  534.  
  535.   }
  536. /*
  537. * RenameFloor()
  538. *
  539. * This function renames a floor.
  540. */
  541. void RenameFloor()
  542.   {
  543.   label FloorName;
  544.   int   ReturnNo;
  545.   if (thisFloor == 0)
  546.     {
  547.     Output_Citadel_Message("USECFG",NULL ,NULL,NULL);
  548.     return ;
  549.  
  550.     }
  551.   if (!getXString("FLRNIT", FloorName, NAMESIZE, NULL, NULL))
  552.   return ;
  553.   if ((ReturnNo = FindFloor(FloorName, FALSE)) != ERROR)
  554.     {
  555.     if (ReturnNo != thisFloor)
  556.       {
  557.       Output_Citadel_Message("ALRYFR",(long)FloorName,NULL,NULL);
  558.       return;
  559.  
  560.       }
  561.  
  562.     }
  563.   ZeroMsgBuffer(&msgBuf);
  564.   sPrintf(msgBuf.mbtext, "The floor %s renamed to %s by %s.",
  565.   FloorTab[thisFloor].FlName, FloorName, logBuf.lbname);
  566.   strCpy(FloorTab[thisFloor].FlName, FloorName);
  567.   putFloor(thisFloor);
  568.   aideMessage(NULL,FALSE);
  569.  
  570.   }
  571. /*
  572. * CreateFloor()
  573. *
  574. * This function creates a floor.
  575. */
  576. void CreateFloor()
  577.   {
  578.   label FloorName;
  579.   int   rover;
  580.   if (  thisRoom == LOBBY ||
  581.   thisRoom == MAILROOM ||
  582.   thisRoom == AIDEROOM  )
  583.     {
  584.     Output_Citadel_Message("CCRFLR",NULL, NULL, NULL);
  585.     return ;
  586.  
  587.     }
  588.   if (!getXString("FLRNIT", FloorName, NAMESIZE, NULL, NULL))
  589.   return ;
  590.   if (FindFloor(FloorName, FALSE) != ERROR)
  591.     {
  592.     Output_Citadel_Message("ALRYFR",(long)FloorName,NULL,NULL);
  593.     return;
  594.  
  595.     }
  596.   for (rover = 1; rover < TopFloor; rover++)
  597.   if (!FloorTab[rover].FlInuse) break;
  598.   if (rover == TopFloor)
  599.     {
  600.     FloorTab = (struct floor *) realloc(FloorTab,
  601.     sizeof *FloorTab * ++TopFloor);
  602.  
  603.     }
  604.   roomBuf.rbFlIndex = rover;
  605.   FloorTab[rover].FlInuse = TRUE;
  606.   strCpy(FloorTab[rover].FlName, FloorName);
  607.   memset(FloorTab[rover].FlModerator, '\0',sizeof(label));
  608.   putFloor(rover);
  609.   putRoom(thisRoom);
  610.   noteRoom();
  611.   ZeroMsgBuffer(&msgBuf);
  612.   sPrintf(msgBuf.mbtext, "The floor %s created by %s.", FloorName,
  613.   logBuf.lbname);
  614.   aideMessage(NULL,FALSE);
  615.  
  616.   }
  617. /*
  618. * putFloor()
  619. *
  620. * This will put a floor record out to disk.
  621. */
  622. void putFloor(int i)
  623.   {
  624.   SYS_FILE name;
  625.   FILE *fd;
  626.   long r;
  627.   extern char *R_W_ANY;
  628.   makeSysName(name, "ctdlflr.sys", &cfg.floorArea);
  629.   if ((fd = safeopen(name, R_W_ANY)) == NULL)
  630.   crashout("Couldn't open the floor file for update!");
  631.   r = i * sizeof *FloorTab;
  632.   fseek(fd, r, 0);
  633.   if (fwrite(FloorTab + i, sizeof *FloorTab, 1, fd) != 1)
  634.   crashout("?putFloor(): write failed!");
  635.   fclose(fd);
  636.  
  637.   }
  638. /*
  639. * KillFloor()
  640. *
  641. * This function kills a floor.
  642. */
  643. void KillFloor()
  644.   {
  645.   int CurrentFloor, CurrentRoom;
  646.   if (roomBuf.rbFlIndex == 0)
  647.     {
  648.     Output_Citadel_Message("NOKILF",NULL ,NULL,NULL);
  649.     return;
  650.  
  651.     }
  652.   if (!getYesNo("CONFRM")) return;
  653.   ZeroMsgBuffer(&msgBuf);
  654.   sPrintf(msgBuf.mbtext, "Floor %s killed by %s.",
  655.   FloorTab[thisFloor].FlName, logBuf.lbname);
  656.   aideMessage(NULL,FALSE);
  657.   CurrentFloor = thisFloor;   /* #define in CTDL.H */
  658.   CurrentRoom  = thisRoom;
  659.   maim = getYesNo("MVALLM");
  660.   FloorRunner(thisRoom, MaimOrKill);
  661.   FloorTab[CurrentFloor].FlInuse = FALSE;
  662.   putFloor(CurrentFloor);
  663.   /* due to behavior of MaimOrKill */
  664.   getRoom((!maim) ? LOBBY : CurrentRoom);
  665.  
  666.   }
  667. /*
  668. * MaimOrKill()
  669. *
  670. * This will kill or move a room to the main floor.
  671. */
  672. int MaimOrKill(int i)
  673.   {
  674.   getRoom(i);
  675.   if (maim)
  676.     {
  677.     roomBuf.rbFlIndex = 0;
  678.  
  679.     }
  680.   else
  681.     {
  682.     roomBuf.rbflags.INUSE = FALSE;
  683.  
  684.     }
  685.   putRoom(i);
  686.   noteRoom();
  687.   return FALSE;
  688.  
  689.   }
  690. /*
  691. * FKnown()
  692. *
  693. * This function will handle the ticklish task of floor display.
  694. */
  695. char FKnown(char mode)
  696.   {
  697.   int         rover, roomNo;
  698.   extern int  DirAlign;
  699.   extern char AlignChar;
  700.   switch (mode)
  701.     {
  702.     case FORGOTTEN:
  703.       Output_Citadel_Message("FORGFL",NULL,NULL,NULL);
  704.     ShowNew = 2;
  705.     SelNew = TRUE;
  706.     RunDisplay();
  707.     SelNew = FALSE;
  708.     break;
  709.     case INT_NOVICE:
  710.     case INT_EXPERT:
  711.     case NOT_INTRO:
  712.     if (SelNew)
  713.       Output_Citadel_Message("RMUNRF",(long)FloorTab[thisFloor].FlName,NULL,NULL);
  714.     ShowNew = TRUE;
  715.     FloorRunner(thisRoom, DispRoom);
  716.     if (mode == INT_NOVICE || mode == NOT_INTRO)
  717.       {
  718.       Output_Citadel_Message("NOUNSN",NULL,NULL,NULL);
  719.       ShowNew = FALSE;
  720.       FloorRunner(thisRoom, DispRoom);
  721.  
  722.       }
  723.     if (SelNew)
  724.       {
  725.       Output_Citadel_Message("OTFLUM",NULL,NULL,NULL);
  726.       for (rover = 0; rover < TopFloor; rover++)
  727.         {
  728.         if (rover != roomBuf.rbFlIndex)
  729.           {
  730.           roomNo = FirstRoom(rover);
  731.           if (FloorRunner(roomNo, RoomHasNew) != ERROR)
  732.             Output_Citadel_Message("FLRNNL", (long)FloorTab[rover].FlName,NULL,NULL);
  733.  
  734.           }
  735.  
  736.         }
  737.  
  738.       }
  739.     break;
  740.     case DR_SEL:
  741.     case SH_SEL:
  742.     case PR_SEL:
  743.     case ANON_SEL:
  744.     case READONLY:
  745.     RunDisplay();
  746.     break;
  747.     default:
  748.     SelNew = TRUE;
  749.     doCR();
  750.     Output_Citadel_Message("FLRWUR", NULL,NULL,NULL);
  751.     ShowNew = FoundNew = TRUE;
  752.     RunDisplay();
  753.     doCR();
  754.     Output_Citadel_Message("FLRWNR", NULL,NULL,NULL);
  755.     ShowNew = FoundNew = FALSE;
  756.     RunDisplay();
  757.     SelNew = FALSE;
  758.  
  759.     }
  760.   return GOOD_SELECT;
  761.  
  762.   }
  763. /*
  764. * RunDisplay()
  765. *
  766. * This will do the actual work of displaying in Floor mode.
  767. */
  768. void RunDisplay()
  769.   {
  770.   extern int  DirAlign;
  771.   extern char AlignChar;
  772.   int rover, roomNo;
  773.   AlignChar = ' ';
  774.   for (rover = 0; rover < TopFloor; rover++)
  775.     {
  776.     if (FloorTab[rover].FlInuse)
  777.       {
  778.       roomNo = FirstRoom(rover);
  779.       if (FloorRunner(roomNo, CheckFloor) != ERROR)
  780.         {
  781.         DispFloorName(rover);
  782.         FloorRunner(roomNo, DispRoom);
  783.         DirAlign = 0;
  784.  
  785.         }
  786.  
  787.       }
  788.  
  789.     }
  790.  
  791.   }
  792. /*
  793. * DispFloorName()
  794. *
  795. * This function displays a floor name with periods, etc...
  796. */
  797. void DispFloorName(int FloorNo)
  798.   {
  799.   int i;
  800.   extern int DirAlign;
  801.   extern char AlignChar;
  802.   Output_Citadel_Message("FLRSNL", (long)FloorTab[FloorNo].FlName,NULL,NULL);
  803.   if (termWidth >= 50)
  804.     {
  805.     DirAlign = 24;
  806.     AlignChar = ' ';
  807.     for (i = strLen(FloorTab[FloorNo].FlName); i < 21; i++)
  808.     mPrintf(".");
  809.  
  810.     }
  811.   else mPrintf("-");
  812.  
  813.   }
  814. /*
  815. * These functions are used as arguments to FloorRunner
  816. */
  817. /*
  818. * RoomHasNew()
  819. *
  820. * This returns TRUE if room has new messages for the current user.
  821. */
  822. int RoomHasNew(int i)
  823.   {
  824.   return (    roomTab[i].rtlastMessage >
  825.   logBuf.lbvisit[logBuf.lbgen[i] & CALLMASK] &&
  826.   roomTab[i].rtlastMessage >= cfg.oldest     );
  827.  
  828.   }
  829. /*
  830. * CheckFloor()
  831. *
  832. * This multipurpose function returns true of one of the combinations is
  833. * true.
  834. */
  835. int CheckFloor(int i)
  836.   {
  837.   #ifdef OLD_STYLE
  838.   if (( SelDirs   &&   roomTab[i].rtflags.ISDIR   ) ||
  839.   ( SelShared &&   roomTab[i].rtflags.SHARED  ) ||
  840.   ( SelPriv   &&   !roomTab[i].rtflags.PUBLIC ) ||
  841.   ( SelAnon   &&   roomTab[i].rtflags.ANON )    ||
  842.   ( SelRO     &&   roomTab[i].rtflags.READ_ONLY )    ||
  843.   ( SelNew && (ShowNew == 2 || (RoomHasNew(i) && FoundNew) ||
  844.   (!RoomHasNew(i) && !FoundNew))))
  845.   return TRUE;
  846.   #else
  847.   if (FlagCheck(i) ||
  848.   ( SelNew && (ShowNew == 2 || (RoomHasNew(i) && FoundNew) ||
  849.   (!RoomHasNew(i) && !FoundNew))))
  850.   return TRUE;
  851.   #endif
  852.   return FALSE;
  853.  
  854.   }
  855. /*
  856. * NSRoomHasNew()
  857. *
  858. * TRUE if room has new messages and isn't skipped.
  859. */
  860. int NSRoomHasNew(int i)
  861.   {
  862.   if (!roomTab[i].rtflags.SKIP && RoomHasNew(i))
  863.   return TRUE;
  864.   if (roomTab[i].rtflags.SKIP) /* Kludge this in -- ugly but useful */
  865.   HasSkipped = TRUE;
  866.   return FALSE;
  867.  
  868.   }
  869. /*
  870. * DispRoom()
  871. *
  872. * This function will display a room name.
  873. */
  874. int DispRoom(int i)
  875.   {
  876.   char HasNew;
  877.   extern char shownHidden;
  878.   HasNew = RoomHasNew(i);
  879.   if (FlagCheck(i) ||
  880.   ( SelNew &&
  881.   (ShowNew == 2 || (HasNew && ShowNew == 1) ||
  882.   (!HasNew && !ShowNew))))
  883.     {
  884.     Output_Citadel_Message("DISPRM",(long)formRoom(i, TRUE, TRUE),NULL,NULL);
  885.     if (!roomTab[i].rtflags.PUBLIC) shownHidden = TRUE;
  886.     if (SelDirs && HalfSysop())
  887.       {
  888.       if (FindDirName(i) != NULL)
  889.         Output_Citadel_Message("DISPDR",(long)FindDirName(i),NULL,NULL);
  890.       else
  891.         Output_Citadel_Message("DISPNF",NULL,NULL,NULL);
  892.  
  893.       }
  894.  
  895.     }
  896.   return FALSE;
  897.  
  898.   }
  899. /*
  900. * Zroom()
  901. *
  902. * This lets us Zforget a room.  Used for ;Z.
  903. */
  904. int Zroom(int i)
  905.   {
  906.   int r;
  907.   if (     i == LOBBY    ||
  908.   i == MAILROOM ||
  909.   i == AIDEROOM      )
  910.     {
  911.     return FALSE;
  912.  
  913.     }
  914.   r = (roomTab[i].rtgen + FORGET_OFFSET) % MAXGEN;
  915.   logBuf.lbgen[i] = r << GENSHIFT;
  916.   return FALSE;
  917.  
  918.   }
  919. /*
  920. * FSroom()
  921. *
  922. * This will skip a room on a floor.
  923. */
  924. int FSroom(int i)
  925.   {
  926.   roomTab[i].rtflags.SKIP = 1;     /* Set bit */
  927.   return FALSE;
  928.  
  929.   }
  930. /*
  931. * FindAny()
  932. *
  933. * This finds any known room on a floor.
  934. */
  935. int FindAny(int i)
  936.   {
  937.   return TRUE;        /* My, that was easy... */
  938.  
  939.   }
  940. static int FlagCheck(int i)
  941.   {
  942.   if (( SelDirs   &&   roomTab[i].rtflags.ISDIR   ) ||
  943.   ( SelShared &&   roomTab[i].rtflags.SHARED  ) ||
  944.   ( SelPriv   &&   !roomTab[i].rtflags.PUBLIC ) ||
  945.   ( SelAnon   &&   roomTab[i].rtflags.ANON )    ||
  946.   ( SelRO     &&   roomTab[i].rtflags.READ_ONLY ))
  947.   return TRUE;
  948.   return FALSE;
  949.  
  950.   }
  951.